package com.demo.java.OD551_600.OD566;

import java.util.Scanner;
import java.util.*;

/**
 * @author bug菌
 * @Source 公众号：猿圈奇妙屋
 * @des： 【最小资金赢得最多选票or选举拉票(B卷-100分)】问题
 * @url： https://blog.csdn.net/weixin_43970743/article/details/146541533
 */
public class OdMain {
    public static void main(String[] args) {
        // 处理输入
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();  // 选举候选人的数量

        int max_b = 1, max_a = 0, result = 0;
        ArrayList<ArrayList<Integer>> tree1 = new ArrayList<>();
        ArrayList<ArrayList<Integer>> f = new ArrayList<>();
        int[] num = new int[40000];
        int[] t = new int[40000];

        // 初始化树状数组和辅助数组
        for (int i = 0; i < 10005; i++) {
            tree1.add(new ArrayList<>());
            f.add(new ArrayList<>());
        }

        // 读取每个候选人的得票数和选择的候选人
        for (int i = 0; i < n; i++) {
            int x = in.nextInt();
            int y = in.nextInt();

            max_a = Math.max(max_a, x);  // 更新最大的候选人编号
            if (y == 0) {
                continue;
            }
            max_b = Math.max(y, max_b);  // 更新最大选择的候选人
            result += y;
            tree1.get(x).add(y);  // 更新候选人的选择列表
        }

        // 按照得票数排序
        for (int i = 1; i <= max_a; ++i) {
            ArrayList<Integer> temp = tree1.get(i);
            if (temp.size() > 0) {
                Collections.sort(temp);  // 排序每个候选人的得票数
                for (int j = 0; j < temp.size(); ++j) {
                    f.get(j + 1).add(temp.get(j));  // 更新排序后的候选人列表
                }
            }
        }

        // 动态规划求解最少投票数
        int k = n;
        int tmp = result;
        for (int i = 1; i <= n; ++i) {
            k -= f.get(i).size();  // 更新候选人的选择数量
            for (int j = 0; j < f.get(i).size(); ++j) {
                change(1, 1, max_b, f.get(i).get(j), num, t);  // 更新树状数组
                tmp -= 1 * f.get(i).get(j);  // 更新结果
            }
            int add = 0;
            if (k <= i) {
                add = query(1, 1, max_b, Math.min(i + 1 - k, n), num, t);  // 查询最少投票数
            }
            result = Math.min(result, tmp + add);  // 更新最小投票数
        }

        // 输出最终结果
        System.out.println(result);
    }

    // 更新树状数组
    public static void change(int x, int l, int r, int q, int[] num, int[] t) {
        if (l == r) {
            ++num[x];
            t[x] += 1 * l;
            return;
        }
        int mid = (l + r) >> 1;
        if (q <= mid) {
            change(x << 1, l, mid, q, num, t);  // 更新左子树
        } else {
            change(x << 1 | 1, mid + 1, r, q, num, t);  // 更新右子树
        }
        t[x] = t[x << 1] + t[x << 1 | 1];  // 合并左右子树
        num[x] = num[x << 1] + num[x << 1 | 1];  // 合并左右子树的节点数
    }

    // 查询树状数组的最小值
    public static int query(int x, int l, int r, int q, int[] num, int[] t) {
        if (l == r) return 1 * l * q;
        int mid = (l + r) >> 1;
        if (q == num[x << 1]) return t[x << 1];  // 返回左子树的结果
        if (q > num[x << 1]) return t[x << 1] + query(x << 1 | 1, mid + 1, r, q - num[x << 1], num, t);  // 查询右子树
        else return query(x << 1, l, mid, q, num, t);  // 查询左子树
    }
}